
/*
功能简介：
实现对两类http请求的响应和处理，配置底层的驱动使用的参数
如基于串口的协议的波特率，是否采用检验位，基于socket连接的协议的ip地址和端口

还有就是新增（删除，编辑）OPC server的变量

编码规范：
  对应的参数获取函数统一命名为 http_+请求路径
  如“/config_driver”的参数获取函数为http_config_driver
  sql相关的插入函数，不应该仅仅以动词select开头，需要加上sql标记

  响应处理函数统一命名为handler+请求路径的格式

主要工作原理：
  因为http库的特殊工作机制，在.c文件内定义了定义了一系列的全局变量，或者以结构体的形式，
  用来临时存放http请求中的参数，这些结构体在头文件内定义
  这些全局变量会马上在后续对应的处理函数中被使用，比如作为构建sql语句的参数

  参数的保存，引入了数据库，并且做了分表的处理，每个变量，都是opc参数一张表，
  和对应的底层驱动一张表，通过变量名，作为唯一的公用主键，在联表查询时使用
  插入的时候是分开插入的，在插入的时候，不设置回调函数，和查询select操作不同

  其实使用数据库的目的，就是实现一种OPC变量的通用回调函数，因为opc变量需要在客户端
  发起请求的时候被马上更新，因此
*/
#include "platform.h"
//#include "MHD_config.h"
//#include "mhd_options.h"
#include <microhttpd.h>
#include <modbus.h>
#include "stdlib.h"
#include <string.h>
#include <sqlite3.h>
#include <cjson/cJSON.h>
#include <string.h>
#include <stdio.h>
#include <open62541.h>

#include <curl/curl.h>

#define POSTBUFFERSIZE 512
#define MAXNAMESIZE 20
#define MAXANSWERSIZE 512
#define GET 0
#define POST 1

// typedef enum MHD_Result
// {
//   MHD_YES=1,MHD_NO
// }int;

struct FtpFile {
  const char *filename;
  FILE *stream;
};

struct connection_info_struct
{
  int connectiontype;
  char *answerstring;
  struct MHD_PostProcessor *postprocessor;
};

//defien struct to store modbus client info
struct modbus_client_info{
  char ip_addr[20];
  int port;
};

//用来接收用户发来的http请求
struct program_update_info{
  char admin_username[32];
  char admin_password[32];
  char program_file_path[128];
};

//用来接收用户发来的http请求
struct frp_connect_info{
  char admin_username[32];
  char admin_password[32];
  char frp_server_addr[32];
  char frp_server_port[16];
  char frp_token[16];
  char http_remote_port[16];
  char opc_ua_remote_port[16];
  char ssh_remote_port[16];
};

struct POST_OPC_UA_history_data{
  char admin_username[32];
  char admin_password[32];
  char name[64];
  char begin_date[32];
  char end_date[32];
};//结构体定义完以后，后面要加一个封号

struct opc_var_config_info{

  char admin_username[32];
  char admin_password[32];
  /*OPC*/
  //char id[16];//independ for each variable
  //name是唯一的标记数据的，sqlite的存储和opc client的查询都是基于name完成的
  char name[64];
  char var_type[32];//uint32 uint16 int32 char
  //Purpose:after process for modbus instruct return value
  char protocol[16];//internal protocol
  //Purpose:only protocol relate attribute will be assign value
  /*OPC*/

  /*DL/T 645*/
  char dlt645_param[512];
  /*DL/T 645*/

  /*modbus RTU*/
  //128个字节不够，基本的例子就需要196个
  char rtu_param[256];
  /*modbus RTU*/
  
  /*modbus tcp*/
  char ip_address[32];
  char port[16];
  char register_type[32];//0:reg 1:coil
  char begin_address[16];
  char offset_range[16];
  //char modbus_tcp_param[256];
  /*modbus tcp*/

  /*DL/T 645*/
  /*
  when it needs to be used,it needs to be converted into a
  32-bit hexadecimal number
  */
  char specification[16];
  char reg_address[32];
  char data_field[256];
  // direction must be read
  /*DL/T 645*/

  /*IEC 104*/
  /*
  在接收http请求的参数的时候，一律采用字符串，因为这样不仅仅方便后续通过和sql进行拼接
  到sql提取出来的时候，再把字符号转换成数值来使用，也是来的及的  
  因为使用的是同一个结构体内去接收的，所以命名要不一样
  */
  char iec_ip_address[32];
  char iec_port[16];
  //typeid对应的是服务端返回数据包的typeid
  char iec_typeid[32];
  /*
  有的时候cot是不需要提供的，
  cot对应的是客户端发送指令的类型，主要是两类
  3:spontaneous 读取
  6:activation 写入操作

  但也可以解释成服务端返回数据时的cot，比如
  20:interrogated by general interrogation
  */
  char iec_cot[32];
  /*
  ASDU报文中数据区域里面，虚拟的起始地址
  */
  //char iec_begin_address[16];
  /*
  用户需要提前查询从机设备对应的点位返回的变量数量
  是单个的数值，还是数组的形式
  */
  //char iec_offset_range[16];
  /*
  用来存储复杂复杂配置信息的数组，甚至可以在里面携带账号密码用于验证，
  在验证符合条件以后，读取的操作，才会返回客户端想要的信息
  直接可以用来替换两个属性
  char iec_begin_address[16];
  char iec_offset_range[16];
  */
  char iec_param[256];
  /*IEC 104*/
};
/*
最特殊的函数，是所有http请求的入口，特定的参数获取函数，和响应处理函数都是其通过if else
在匹配请求路径后，通过路由的方式进行调用的，API接口都通过postman进行测试过，前端可以放心接入
前端传参时，需要选择post请求，在body中选择form-data，目前的后端才可以正常完成解析。

*/
enum MHD_Result RESTful_API_Entry(void *cls, struct MHD_Connection *connection,
      const char *url, const char *method,const char *version, 
      const char *upload_data,size_t *upload_data_size, void **con_cls);

enum MHD_Result send_page (struct MHD_Connection *connection, const char *page);

enum MHD_Result http_config_driver (void *coninfo_cls, enum MHD_ValueKind kind, 
      const char *key,const char *filename, const char *content_type,
      const char *transfer_encoding, const char *data, uint64_t off,size_t size);

enum MHD_Result http_add_opc_var(void *coninfo_cls, enum MHD_ValueKind kind,
      const char *key,const char *filename, const char *content_type,
      const char *transfer_encoding, const char *data, uint64_t off, size_t size);

enum MHD_Result handler_add_var(struct connection_info_struct *con_info,size_t *upload_data_size,
        struct MHD_Connection *connection,const char *upload_data);

enum MHD_Result handler_opc_auth(struct connection_info_struct *con_info,size_t *upload_data_size,
        struct MHD_Connection *connection,const char *upload_data);

enum MHD_Result handler_opc_auth_update(struct connection_info_struct *con_info,size_t *upload_data_size,
        struct MHD_Connection *connection,const char *upload_data);

enum MHD_Result handler_frp_info_update(struct connection_info_struct *con_info,size_t *upload_data_size,
        struct MHD_Connection *connection,const char *upload_data);

enum MHD_Result PP_OPC_UA_delete_var(void *coninfo_cls, enum MHD_ValueKind kind, const char *key,
  const char *filename, const char *content_type,
  const char *transfer_encoding, const char *data, uint64_t off, size_t size);

enum MHD_Result handler_OPC_UA_delete_var(struct connection_info_struct *con_info,size_t *upload_data_size,
        struct MHD_Connection *connection,const char *upload_data);

enum MHD_Result handler_OPC_UA_history_data(struct connection_info_struct *con_info,size_t *upload_data_size,
        struct MHD_Connection *connection,const char *upload_data);

enum MHD_Result handler_manage_program_update(struct connection_info_struct *con_info,size_t *upload_data_size,
        struct MHD_Connection *connection,const char *upload_data);

enum MHD_Result handler_manage_program_restart(struct connection_info_struct *con_info,size_t *upload_data_size,
        struct MHD_Connection *connection,const char *upload_data);

char* sql_insert_opc_var();     
//void sql_insert_opc_var();
void sql_insert_modbus_reg();
void sql_insert_dlt_645();
void sql_insert_iec_104_measure();

int ini_file_frp_info_update();